//! 资源路由器
//!
//! 根据上下文路由到正确的资源，支持层级回退

use super::{ResourceContext, ResourceError, ResourceManager, ResourceResult};
use std::sync::Arc;
use tracing::debug;

/// 资源来源信息
#[derive(Debug, Clone)]
pub struct ResourceSource {
    /// 资源代码
    pub code: String,
    /// 资源键
    pub key: String,
    /// 回退层级（0 表示当前层级，1 表示上一层级，以此类推）
    pub fallback_level: usize,
}

/// 资源路由器
///
/// 根据上下文路由到正确的资源，支持层级回退查询
///
/// # 类型参数
///
/// - `T`: 资源类型
/// - `M`: 资源管理器类型
pub struct ResourceRouter<T, M>
where
    M: ResourceManager<T>,
{
    manager: Arc<M>,
    _phantom: std::marker::PhantomData<T>,
}

impl<T, M> ResourceRouter<T, M>
where
    M: ResourceManager<T>,
{
    /// 创建新的资源路由器
    pub fn new(manager: Arc<M>) -> Self {
        Self { manager, _phantom: std::marker::PhantomData }
    }

    /// 获取当前层级的资源
    ///
    /// # 参数
    ///
    /// - `context`: 资源上下文
    ///
    /// # 返回
    ///
    /// 返回资源和来源信息
    pub async fn get_resource(
        &self,
        context: &ResourceContext,
    ) -> ResourceResult<(Arc<T>, ResourceSource)> {
        let code = context.current_code();
        let key = context.resource_key(code);

        let resource = self.manager.load_resource(context, code).await?;

        debug!("获取资源: code={}, key={}", code, key);

        Ok((resource, ResourceSource { code: code.to_string(), key, fallback_level: 0 }))
    }

    /// 获取带回退的资源列表
    ///
    /// 按照层级回退顺序返回所有可用的资源
    ///
    /// # 参数
    ///
    /// - `context`: 资源上下文
    ///
    /// # 返回
    ///
    /// 返回资源列表，按优先级从高到低排序
    pub async fn get_resources_with_fallback(
        &self,
        context: &ResourceContext,
    ) -> ResourceResult<Vec<(Arc<T>, ResourceSource)>> {
        let fallback_codes = context.hierarchy.fallback_order();
        let mut resources = Vec::new();

        for (level, code) in fallback_codes.iter().enumerate() {
            let key = context.resource_key(code);

            match self.manager.load_resource(context, code).await {
                Ok(resource) => {
                    debug!("获取资源成功: code={}, key={}, level={}", code, key, level);
                    resources.push((resource, ResourceSource { code: code.clone(), key, fallback_level: level }));
                },
                Err(e) => {
                    debug!("获取资源失败: code={}, key={}, error={:?}", code, key, e);
                    // 继续尝试下一个层级
                    continue;
                },
            }
        }

        if resources.is_empty() {
            return Err(ResourceError::ResourceNotFound(format!("未找到任何可用资源: {}", context.current_code())));
        }

        Ok(resources)
    }
}

impl<T, M> Clone for ResourceRouter<T, M>
where
    M: ResourceManager<T>,
{
    fn clone(&self) -> Self {
        Self { manager: self.manager.clone(), _phantom: std::marker::PhantomData }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::resource::{ResourceContext, ResourceHierarchy};
    use async_trait::async_trait;

    struct MockManager;

    #[async_trait]
    impl ResourceManager<String> for MockManager {
        async fn load_resource(
            &self,
            _context: &ResourceContext,
            code: &str,
        ) -> ResourceResult<Arc<String>> {
            Ok(Arc::new(format!("resource_{}", code)))
        }

        async fn initialize(&self) -> ResourceResult<()> {
            Ok(())
        }
    }

    #[tokio::test]
    async fn test_router_get_resource() {
        let manager = Arc::new(MockManager);
        let router = ResourceRouter::new(manager);

        let hierarchy = ResourceHierarchy::single_level("610100", "西安市");
        let context = ResourceContext::new(hierarchy);

        let (resource, source) = router.get_resource(&context).await.unwrap();
        assert_eq!(*resource, "resource_610100");
        assert_eq!(source.code, "610100");
        assert_eq!(source.fallback_level, 0);
    }
}
